package com.ruoyi.common.utils.file;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class ZipUtils {
	public ZipUtils() {
	}

	public static void createZipFileOfDirectory(File srcDir, File zipOutput)
			throws IOException {

		if (srcDir.exists() && srcDir.isDirectory()) {
			if (zipOutput == null) {
				zipOutput = new File(srcDir.getPath() + ".zip");
			}

			if (zipOutput.exists() && !zipOutput.isFile()) {
				throw new IllegalArgumentException(zipOutput.getAbsolutePath()
						+ " exist but not a file!");
			} else {
				ZipOutputStream zipOutputStream = null;
				String baseName = srcDir.getAbsolutePath() + File.pathSeparator;

				try {
					zipOutputStream = new ZipOutputStream(new FileOutputStream(
							zipOutput));
					addDirToZip(srcDir, zipOutputStream, baseName);
				} finally {
					IOUtils.closeQuietly(zipOutputStream);
				}

			}
		} else {
			throw new IllegalArgumentException(srcDir.getAbsolutePath()
					+ "is not a directory");
		}
	}

	public static void addFilesToZip(ArrayList<File> files, File zipOutput)
			throws FileNotFoundException, IOException {
		ZipOutputStream zipOutputStream = null;
		if (zipOutput.exists()) {
			zipOutput.delete();
		}

		zipOutputStream = new ZipOutputStream(new FileOutputStream(zipOutput));
		Iterator var4 = files.iterator();

		while (var4.hasNext()) {
			File srcDir = (File) var4.next();
			if (!srcDir.exists()) {
				throw new IllegalArgumentException(srcDir.getAbsolutePath()
						+ "is not a directory");
			}

			if (zipOutput == null) {
				zipOutput = new File(srcDir.getPath() + ".zip");
			}

			if (zipOutput.exists() && !zipOutput.isFile()) {
				throw new IllegalArgumentException(zipOutput.getAbsolutePath()
						+ " exist but not a file!");
			}

			if (srcDir.isDirectory()) {
				String baseName = srcDir.getAbsolutePath() + File.pathSeparator;
				addDirToZip(srcDir, zipOutputStream, baseName);
			} else {
				addFileToZip(srcDir, zipOutputStream);
			}
		}

		IOUtils.closeQuietly(zipOutputStream);
	}

	private static void addDirToZip(File dir, ZipOutputStream zip,
			String baseName) throws IOException {
		File[] files = dir.listFiles();
		File[] var7 = files;
		int var6 = files.length;

		for (int var5 = 0; var5 < var6; ++var5) {
			File file = var7[var5];
			if (file.isDirectory()) {
				addDirToZip(file, zip, baseName);
			} else {
				String entryName = file.getAbsolutePath().substring(
						baseName.length());
				ZipEntry zipEntry = new ZipEntry(entryName);
				zip.putNextEntry(zipEntry);
				FileInputStream fileInput = new FileInputStream(file);

				try {
					IOUtils.copy(fileInput, zip);
					zip.closeEntry();
				} finally {
					IOUtils.closeQuietly(fileInput);
				}
			}
		}

	}

	private static void addFileToZip(File file, ZipOutputStream zip)
			throws IOException {
		String entryName = file.getName();
		ZipEntry zipEntry = new ZipEntry(entryName);
		zip.putNextEntry(zipEntry);
		FileInputStream fileInput = new FileInputStream(file);

		try {
			IOUtils.copy(fileInput, zip);
			zip.closeEntry();
		} finally {
			IOUtils.closeQuietly(fileInput);
		}

	}

	public static void unzipFileToDirectory(File zipFile, File targetDir)
			throws IOException {
		if (zipFile.exists() && zipFile.isFile()) {
			if (targetDir == null) {
				targetDir = new File(("" + zipFile.getAbsoluteFile()).replace(
						".zip", ""));
				targetDir.mkdir();
			}

			if (targetDir.exists() && targetDir.isDirectory()) {
				if (targetDir.listFiles().length != 0) {
					throw new IllegalArgumentException(
							targetDir.getAbsolutePath() + "is not empty");
				} else {
					ZipInputStream zis = new ZipInputStream(
							new FileInputStream(zipFile));

					for (ZipEntry zipEntry = zis.getNextEntry(); zipEntry != null; zipEntry = zis
							.getNextEntry()) {
						String entryFileName = zipEntry.getName();
						File newFile = new File(targetDir, entryFileName);
						if (zipEntry.isDirectory()) {
							if (!newFile.exists()) {
								newFile.mkdirs();
							} else if (!newFile.isDirectory()) {
								throw new RuntimeException(
										newFile.getAbsolutePath()
												+ "already exists and is not a directory.");
							}
						} else {
							(new File(newFile.getParent())).mkdirs();
							FileOutputStream fos = new FileOutputStream(newFile);

							try {
								IOUtils.copy(zis, fos);
							} finally {
								IOUtils.closeQuietly(fos);
							}
						}
					}

					zis.closeEntry();
					IOUtils.closeQuietly(zis);
				}
			} else {
				throw new IllegalArgumentException(targetDir.getAbsolutePath()
						+ "is not a Directory");
			}
		} else {
			throw new IllegalArgumentException(zipFile.getAbsolutePath()
					+ "is not a file");
		}
	}

	public static void zip(String zipFileName, String relativePath,
			String directory) throws FileNotFoundException, IOException {
		String fileName = zipFileName;
		if (zipFileName == null || zipFileName.trim().equals("")) {
			File temp = new File(directory);
			if (temp.isDirectory()) {
				fileName = directory + ".zip";
			} else if (directory.indexOf(".") > 0) {
				fileName = directory.substring(0, directory.lastIndexOf("."))
						+ "zip";
			} else {
				fileName = directory + ".zip";
			}
		}

		ZipOutputStream zos = new ZipOutputStream(
				new FileOutputStream(fileName));

		try {
			zip(zos, relativePath, directory);
		} catch (IOException var9) {
			throw var9;
		} finally {
			if (zos != null) {
				zos.close();
			}

		}

	}

	private static void zip(ZipOutputStream zos, String relativePath,
			String absolutPath) throws IOException {
		File file = new File(absolutPath);
		if (file.isDirectory()) {
			File[] files = file.listFiles();

			for (int i = 0; i < files.length; ++i) {
				File tempFile = files[i];
				if (tempFile.isDirectory()) {
					String newRelativePath = relativePath + tempFile.getName()
							+ File.separator;
					createZipNode(zos, newRelativePath);
					zip(zos, newRelativePath, tempFile.getPath());
				} else {
					zipFile(zos, tempFile, relativePath);
				}
			}
		} else {
			zipFile(zos, file, relativePath);
		}

	}

	private static void zipFile(ZipOutputStream zos, File file,
			String relativePath) throws IOException {
		ZipEntry entry = new ZipEntry(relativePath + file.getName());
		zos.putNextEntry(entry);
		FileInputStream is = null;

		try {
			is = new FileInputStream(file);
			int BUFFERSIZE = 2048;
			// int length = false;
			byte[] buffer = new byte[BUFFERSIZE];

			int length;
			while ((length = is.read(buffer, 0, BUFFERSIZE)) >= 0) {
				zos.write(buffer, 0, length);
			}

			zos.flush();
			zos.closeEntry();
		} catch (IOException var11) {
			throw var11;
		} finally {
			if (is != null) {
				is.close();
			}

		}
	}

	private static void createZipNode(ZipOutputStream zos, String relativePath)
			throws IOException {
		ZipEntry zipEntry = new ZipEntry(relativePath);
		zos.putNextEntry(zipEntry);
		zos.closeEntry();
	}

	public static void unzip(String zipFilePath, String toPath)
			throws IOException {
		OutputStream os = null;
		InputStream is = null;
		ZipFile zipFile = null;
		File toFile = new File(toPath);
		if (!toFile.exists()) {
			toFile.mkdirs();
		}

		try {
			zipFile = new ZipFile(zipFilePath);
			String directoryPath = "";
			if (toPath != null && !"".equals(toPath)) {
				directoryPath = toPath;
			} else {
				directoryPath = zipFilePath.substring(0,
						zipFilePath.lastIndexOf("."));
			}

			directoryPath = directoryPath.replaceAll("[\\\\]", "/");
			directoryPath = directoryPath.endsWith("/") ? directoryPath
					.substring(0, directoryPath.length() - 1) : directoryPath;
			Enumeration<? extends ZipEntry> entryEnum = zipFile.entries();
			if (entryEnum != null) {
				ZipEntry zipEntry = null;

				while (true) {
					while (entryEnum.hasMoreElements()) {
						zipEntry = entryEnum.nextElement();
						String temp_path;
						File file;
						if (zipEntry.isDirectory()) {
							temp_path = directoryPath + "/"
									+ zipEntry.getName();
							file = new File(temp_path);
							if (!file.exists()) {
								file.mkdirs();
							}
						} else {
							temp_path = directoryPath + "/"
									+ zipEntry.getName();
							file = new File(temp_path);
							os = new BufferedOutputStream(new FileOutputStream(
									file));
							is = zipFile.getInputStream(zipEntry);
							byte[] buffer = new byte[4096];
							boolean var12 = false;

							int readLen;
							while ((readLen = is.read(buffer, 0, 4096)) >= 0) {
								os.write(buffer, 0, readLen);
							}

							os.flush();
							os.close();
						}
					}

					return;
				}
			}
		} catch (IOException var16) {
			throw var16;
		} finally {
			if (zipFile != null) {
				zipFile.close();
				zipFile = null;
			}

			if (is != null) {
				is.close();
			}

			if (os != null) {
				os.close();
			}

		}

	}


	public static void unzip2(File zipFile, String descDir) {
		System.out.println("解压文件的当前路径为:"+ descDir);
		try (ZipArchiveInputStream inputStream = getZipFile(zipFile)) {
			File pathFile = new File(descDir);
			if (!pathFile.exists()) {
				pathFile.mkdirs();
			}
			ZipArchiveEntry entry = null;
			while ((entry = inputStream.getNextZipEntry()) != null) {
				if (entry.isDirectory()) {
					File directory = new File(descDir, entry.getName());
					directory.mkdirs();
				} else {
					OutputStream os = null;
					try {
						os = new BufferedOutputStream(new FileOutputStream(new File(descDir, entry.getName())));
						//输出文件路径信息
//						System.out.println("解压文件的当前路径为:{}"+ descDir + entry.getName());
						org.apache.commons.compress.utils.IOUtils.copy(inputStream, os);
					} finally {
						org.apache.commons.compress.utils.IOUtils.closeQuietly(os);
					}
				}
			}
			final File[] files = pathFile.listFiles();
			if (files != null && files.length == 1 && files[0].isDirectory()) {
				// 说明只有一个文件夹
				FileUtils.copyDirectory(files[0], pathFile);
				//免得删除错误， 删除的文件必须在/data/demand/目录下。
				boolean isValid = files[0].getPath().contains("/data/www/");
				if (isValid) {
					FileUtils.forceDelete(files[0]);
				}
			}
			System.out.println("******************解压完毕********************");

		} catch (Exception e) {
			System.out.println("[unzip] 解压zip文件出错"+e);
		}
	}

	private static ZipArchiveInputStream getZipFile(File zipFile) throws Exception {
		return new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile)),"GBK");
	}


	/**
	 * 下载文件
	 * @param response
	 * @param file
	 */
	public static  void download(HttpServletResponse response, File file){
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		OutputStream os = null;

		try {
			os = response.getOutputStream();
			fis = new FileInputStream(file);
			bis = new BufferedInputStream(fis);
			byte[] buffer = new byte[1024];
			int len = 0;
			while((len = fis.read(buffer)) != -1){
				os.write(buffer, 0, len);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			bis.close();
			fis.close();
			os.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
